import { h, defineComponent, reactive, onMounted, onUnmounted } from "@vue/runtime-core";
import { hitTestObject, getRandomRange, parseConfig, enemyPlaneConfig } from "../utils/index";
import { game } from "../Game";

import { planeWidth, planeHeight, enemyPlaneHeight, bulletWidth, bulletHeight } from "../utils/gameConfig";

import EnemyPlane from "../component/EnemyPlane";
import Plane from "../component/Plane";
import Bullet from "../component/Bullet";
// 把 map 抽离出来
// import battleImg from "../../assets/battle.jpg";
import Map from "../component/Map";
export default defineComponent({
	setup(props, { emit }) {
		// vue3 响应式对象 引用类型 reactive
		// 创建引用类型的 飞机信息 传给子组件飞机容器 去改变位置
		const { planeInfo } = createPlaneInfo()
		// 创建子弹
		const { bullets, addBullet } = createBulletsInfo()
		// 创建敌机
		// {planesInfo: enemyPlanesInfo} 将从对象中提取左边重命名为右边
		let { planesInfo: enemyPlanesInfo, changeEnemyPlanesInfo, deleteEnemyPlane } = createEnemyPlanesInfo();
		// 添加子弹
		const onAttack = (bulletInfo) => {
			addBullet(bulletInfo)
		};
		// 战斗逻辑
		useFighting(planeInfo, bullets, enemyPlanesInfo, emit, changeEnemyPlanesInfo, deleteEnemyPlane)

		return {
			planeInfo,
			enemyPlanesInfo,
			bullets,
			onAttack
		};
	},

	render(ctx) {
		// DOM
		// <div><img src="imgPath" /></div>
		// pixi
		// <container><sprite texture="imgPath"></sprite></container>
		// return h("Container", [h("Sprite", { texture: battleImg })])

		let createEnemyPlanes = () => {
			return ctx.enemyPlanesInfo.map((info) => {
				return h(EnemyPlane, { x: info.x, y: info.y, planeIndex: info.planeIndex });
			});
		};
		let createBullets = () => {
			return ctx.bullets.map((info) => {
				return h(Bullet, { x: info.x, y: info.y });
			})
		}
		// 基于响应式值对象 -> vnode -> dom element
		return h("Container", [
			h(Map),
			// 监听子组件的 attack 事件，on+单词首字母大写
			h(Plane, { x: ctx.planeInfo.x, y: ctx.planeInfo.y, onAttack: ctx.onAttack }),
			// h(EnemyPlane, { x: ctx.enemyPlanesInfo[0].x, y: ctx.enemyPlanesInfo[0].y }),
			...createEnemyPlanes(),
			...createBullets()
		])
	}
});

function useFighting(planeInfo, bullets, enemyPlanesInfo, emit, changeEnemyPlanesInfo, deleteEnemyPlane) {
	let round = 1;
	const speed = 2;
	const mapHeight = game.screen.height;

	const handleTicker = () => {
		// 子弹移动，碰撞检测
		bullets.forEach((info, b) => {
			info.y--;
			enemyPlanesInfo.forEach((enemy, e) => {
				if (hitTestObject(info, enemy)) {
					console.log("子弹命中");
					// bug 子弹命中敌军后，剩余的子弹会瞬移...
					bullets.splice(b, 1);
					enemyPlanesInfo.splice(e, 1);
				}
			})
		})

		// 我方飞机移动,不出界
		planeInfo.x = Math.max(0, Math.min(planeInfo.x + planeInfo.horiDir * speed * 2, game.screen.width - planeWidth));
		planeInfo.y = Math.max(0, Math.min(planeInfo.y + planeInfo.vertDir * speed * 2, game.screen.height - planeHeight));

		// 敌方飞机移动
		if (
			Object.hasOwnProperty.call(enemyPlanesInfo, length) &&
			enemyPlanesInfo.length != null &&
			enemyPlanesInfo.length > 0
		) {
			for (let i = 0; i < enemyPlanesInfo.length; i++) {
				const element = enemyPlanesInfo[i];
				// element.x += getRandomRange(-speed*2,speed*2);
				// if (element.x>=game.screen.width*0.9) {
				// 	element.x -= getRandomRange(speed*2,speed*3);
				// }else if (element.x<=game.screen.width*0.1) {
				// 	element.x += getRandomRange(speed*2,speed*3);
				// }
				element.y += getRandomRange(speed, speed * 2);
				// 老师的矩形碰撞
				if (hitTestObject(element, planeInfo)) {
					console.log(`Hit${element.planeIndex}`);
					// 状态清零不管用，是因为写成了函数的值的形式，改为调用函数就能实现状态重置了
					// 跳转到结束页面
					emit("changePage", "EndPage", "你输了")
				}
				if (element.y >= mapHeight - enemyPlaneHeight) {
					// 根据编号，从敌机数组中移除飞机，现在暂时移除第一架飞机✈
					if (i == enemyPlanesInfo.length - 1) {
						if (round == enemyPlaneConfig.length) {
							console.log("您已通关");
							emit("changePage", "EndPage", "你赢了");
						} else {
							changeEnemyPlanesInfo();
							round++;
						}
						console.log(`第${round}关:`);
					}

				}
			}
		}
	};

	onMounted(() => {
		game.ticker.add(handleTicker)
	});

	onUnmounted(() => {
		game.ticker.remove(handleTicker)
	});
}

function createPlaneInfo() {
	const planeInfo = reactive({
		x: getRandomRange(game.screen.width / 2, game.screen.width) - planeWidth,
		y: getRandomRange(game.screen.height / 2, game.screen.height) - planeHeight,
		width: planeWidth,
		height: planeHeight
	})

	planeInfo.horiDir = 0;
	planeInfo.vertDir = 0;

	// 键盘控制 keydown
	window.addEventListener("keydown", (e) => {
		switch (e.code) {
			case "ArrowUp":
				planeInfo.vertDir = -1;
				break;
			case "ArrowDown":
				planeInfo.vertDir = 1;
				break;
			case "ArrowLeft":
				planeInfo.horiDir = -1;
				break;
			case "ArrowRight":
				planeInfo.horiDir = 1;
				break;
			default:
				break;
		}
	});

	window.addEventListener("keyup", (e) => {
		switch (e.code) {
			case "ArrowUp":
			case "ArrowDown":
				planeInfo.vertDir = 0;
				break;
			case "ArrowLeft":
			case "ArrowRight":
				planeInfo.horiDir = 0;
				break;
			default:
				break;
		}
	});

	return { planeInfo };
}

function createEnemyPlanesInfo() {
	// 初始值
	let round = 1;
	let planesInfo = reactive(parseConfig(enemyPlaneConfig[0]));
	// 通过增删数组元素来切换关卡，不能直接赋值替换数组
	const changeEnemyPlanesInfo = () => {
		// planesInfo.push({ x: 100, y: 100, width: 64, height: 64, planeIndex: 101 })
		if (round < enemyPlaneConfig.length) {
			let arr = parseConfig(enemyPlaneConfig[round++]);
			for (let i = 0; i < arr.length; i++) {
				planesInfo.push(arr[i])
			}
		}
	}
	const deleteEnemyPlane = (index) => {
		// 删除 0 1 后，其他的飞机也跟着变为 0 1 触发自动删除所有
		if (index < planesInfo.length) {
			planesInfo.splice(index, 1);
		}
	}
	// window.addEventListener("keydown", (e) => {
	// 	switch (e.code) {
	// 		case "KeyQ":
	// 			planesInfo.shift();
	// 			break;
	// 		default:
	// 			break;
	// 	}
	// });

	return { planesInfo, changeEnemyPlanesInfo, deleteEnemyPlane }
}

function createBulletsInfo() {
	const bullets = reactive([])
	const addBullet = (args) => {
		bullets.push({ ...args, width: bulletWidth, height: bulletHeight })
	}
	return { bullets, addBullet };
}